package me.zfz.business.service;

import me.zfz.base.bean.SmartResponse;
import me.zfz.base.bean.TreeProp;
import me.zfz.base.constant.IConstant;
import me.zfz.base.exception.DaoException;
import me.zfz.base.exception.ServiceException;
import me.zfz.base.helper.ObjectHelper;
import me.zfz.base.service.impl.MgrServiceImpl;
import me.zfz.business.bean.UserInfo;
import me.zfz.business.bean.entity.StudentInfo;
import me.zfz.business.bean.entity.TNOrg;
import me.zfz.business.bean.entity.TNUser;
import me.zfz.business.constant.enums.OrgType;
import me.zfz.business.dao.impl.OrgDao;
import me.zfz.business.dao.impl.StudentInfoDao;
import me.zfz.business.dao.impl.UserDao;
import me.zfz.business.bean.UserSearchParam;
import me.zfz.base.helper.TreeCombinHelper;
import me.zfz.base.plugins.OrgUserZTreeData;
import me.zfz.base.plugins.ZTreeHelper;
import com.mixsmart.security.SecurityUtils;
import com.mixsmart.utils.LoggerUtils;
import com.mixsmart.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;

/**
 * @author author
 */
@Service
public class UserService extends MgrServiceImpl<TNUser> {

    @Autowired
    private UserDao userDao;
    @Autowired
    private OrgDao orgDao;
    @Autowired
    private TreeCombinHelper treeCombinHelper;
    @Autowired
    private OrgService orgServ;
    @Autowired
    private StudentInfoDao studentInfoDao;

    /**
     * 根据searchParam参数查询用户信息
     *
     * @param searchParam
     * @param start
     * @param rows
     * @return
     * @throws ServiceException
     */
    public SmartResponse<Object> findAllObj(UserSearchParam searchParam, int start, int rows) throws ServiceException {
        SmartResponse<Object> smartResp = new SmartResponse<Object>();
        smartResp.setResult(IConstant.OP_NOT_DATA_SUCCESS);
        smartResp.setMsg(IConstant.OP_NOT_DATA_SUCCESS_MSG);
        try {
            List<Object> objs = userDao.queryObjPage(searchParam, start, rows);
            if (null != objs && objs.size() > 0) {
                smartResp.setResult(IConstant.OP_SUCCESS);
                smartResp.setMsg(IConstant.OP_SUCCESS_MSG);
                objs = ObjectHelper.handleObjDate(objs);
                smartResp.setDatas(objs);
                long total = userDao.queryObjCount(searchParam);
                smartResp.setTotalNum(total);
                smartResp.setTotalPage(getTotalPage(total, rows));
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }


    /**
     * 保存用户信息
     *
     * @param user
     * @return
     * @throws ServiceException
     */
    public SmartResponse<String> save(TNUser user) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<String>();
        try {
            if (null != user) {
                String userName = user.getUsername() == null ? "" : user.getUsername();
                if (userDao.isExistUsername(userName)) {
                    smartResp.setResult(IConstant.OP_FAIL);
                    smartResp.setMsg("该用户名已存在，不能再注册！");
                    return smartResp;
                }
                user.setPassword(SecurityUtils.md5(user.getPassword()));
                Serializable id = userDao.save(user);
                if (null != id) {
                    smartResp.setResult(IConstant.OP_SUCCESS);
                    smartResp.setMsg("用户添加成功");
                    smartResp.setData(id.toString());
                }
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }


    @Override
    public SmartResponse<String> update(TNUser user) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<String>();
        try {
            if (null != user) {
                TNUser oldUser = userDao.queryUser(user.getUsername());
                if (null != oldUser && !oldUser.getId().equals(user.getId())) {//如果用户名被修改了 ，就需要验证新名字是否冲突
                    smartResp.setResult(IConstant.OP_FAIL);
                    smartResp.setMsg("该用户名已存在，不能再注册！");
                } else {
                    boolean is;
                    if (null != oldUser && oldUser.getId().equals(user.getId())) {
                        oldUser.setUsername(user.getUsername());
                        oldUser.setEmail(user.getEmail());
                        oldUser.setFullName(user.getFullName());
                        oldUser.setMobileNo(user.getMobileNo());
                        oldUser.setOrgId(user.getOrgId());
                        oldUser.setQq(user.getQq());
                        oldUser.setRemark(user.getRemark());
                        oldUser.setState(user.getState());
                        oldUser.setAuditFlag(user.getAuditFlag());
                        oldUser.setRoleId(user.getRoleId());
                        is = userDao.update(oldUser);
                    } else {
                        is = userDao.update(user);
                    }
                    if (is) {
                        smartResp.setResult(IConstant.OP_SUCCESS);
                        smartResp.setMsg("用户信息修改成功");
                        smartResp.setData(user.getId());
                    }
                }
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }

    /**
     * 删除用户信息
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public SmartResponse<String> del(String id) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<String>();
        try {
            if (null != id) {
                if (userDao.delete(id)) {
                    smartResp.setResult(IConstant.OP_SUCCESS);
                    smartResp.setMsg("用户数据删除成功");
                }
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     * @throws ServiceException
     */
    public SmartResponse<UserInfo> login(String username, String password) throws ServiceException {
        SmartResponse<UserInfo> smartResp = new SmartResponse<>();
        try {
            if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {
                String md5Pwd = SecurityUtils.md5(password);
                TNUser user = userDao.queryLogin(username, md5Pwd);
                if (null != user) {
                    UserInfo userInfo = getUserInfo(user);
                    smartResp.setResult(IConstant.OP_SUCCESS);
                    smartResp.setMsg(IConstant.OP_SUCCESS_MSG);
                    smartResp.setData(userInfo);
                } else {
                    LoggerUtils.info(logger, "用户名或密码错误--输入用户名[" + username + "]---");
                }
            } else {
                LoggerUtils.info(logger, "用户名或密码为空--");
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }

    /**
     * 获取用户信息
     *
     * @param user 用户实体对象
     * @return 返回用户信息
     */
    public UserInfo getUserInfo(TNUser user) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setUsername(user.getUsername());
        userInfo.setFullName(user.getFullName());
        userInfo.setAuditFlag(user.getAuditFlag());
        TNOrg selfOrg = null;
        List<String> deptId;
        if (Objects.equals("0", user.getOrgId())) {
            deptId = new ArrayList<>(1);
            deptId.add(user.getOrgId());
        } else {
            List<TNOrg> orgSelfAndChildren = orgDao.querySelfAndChildren(user.getOrgId());
            deptId = new ArrayList<>(orgSelfAndChildren.size());
            for (TNOrg tnOrg : orgSelfAndChildren) {
                deptId.add(tnOrg.getId());
                if (Objects.equals(user.getOrgId(), tnOrg.getId())) {
                    selfOrg = tnOrg;
                }
            }
        }
        if (null != selfOrg) {
            userInfo.setDeptName(selfOrg.getName());
            userInfo.setSeqDeptNames(selfOrg.getSeqNames());
            userInfo.setOrgId(selfOrg.getId());
            if (OrgType.ZY.getValue().equals(selfOrg.getType())) {
                userInfo.setDepartmentId(selfOrg.getId());
            }
        } else {
            userInfo.setOrgId(user.getOrgId());
        }
        List<String> roles = new ArrayList<>(1);
        roles.add(user.getRoleId());
        userInfo.setMenuRoleIds(roles);
        userInfo.setRoleIds(roles);
        userInfo.setOrgIds(deptId);
        boolean isAdmin = !Objects.equals("01337e1d2666412fa3d028136ff710f7", user.getRoleId());
        if (!isAdmin) {
            Map<String, Object> params = new HashMap<>(1);
            params.put("userId", user.getId());
            List<StudentInfo> studentInfos = studentInfoDao.querySql("SELECT * from student_info where user_id = :userId", params);
            if (studentInfos != null && studentInfos.size() > 0) {
                StudentInfo studentInfo = studentInfos.get(0);
                if (studentInfo != null) {
                    userInfo.setStuId(studentInfo.getId());
                }
            }
        }
        return userInfo;
    }

    /**
     * 批量修改密码
     *
     * @param userIds
     * @param pwd
     * @param confirmPwd
     * @return
     * @throws ServiceException
     */
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
    public SmartResponse<String> batchChangePwd(String userIds, String pwd, String confirmPwd) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<String>();
        try {
            if (StringUtils.isNotEmpty(userIds) && StringUtils.isNotEmpty(pwd) && StringUtils.isNotEmpty(confirmPwd)) {
                if (pwd.equals(confirmPwd)) {
                    String[] userIdArray = userIds.split(",");
                    pwd = SecurityUtils.md5(pwd);
                    if (userDao.batchChangePwd(userIdArray, pwd)) {
                        smartResp.setResult(IConstant.OP_SUCCESS);
                        smartResp.setMsg("密码修改成功");
                    } else
                        smartResp.setMsg("密码修改失败");
                    userIdArray = null;
                } else {
                    smartResp.setMsg("两次输入的密码不一致");
                }
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }


    /**
     * 修改密码
     *
     * @param userId
     * @param oldPwd
     * @param newPwd
     * @param confirmNewPwd
     * @return
     * @throws ServiceException
     */
    public SmartResponse<String> changePwd(String userId, String oldPwd, String newPwd, String confirmNewPwd) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<String>();
        try {
            if (StringUtils.isNotEmpty(userId) && StringUtils.isNotEmpty(oldPwd)
                    && StringUtils.isNotEmpty(newPwd) && StringUtils.isNotEmpty(confirmNewPwd)) {
                if (newPwd.equals(confirmNewPwd)) {
                    TNUser user = userDao.find(userId);
                    if (null != user) {
                        String md5Pwd = SecurityUtils.md5(oldPwd);
                        if (user.getPassword().equals(md5Pwd)) {
                            String md5NewPwd = SecurityUtils.md5(newPwd);
                            if (userDao.changePwd(userId, md5NewPwd)) {
                                smartResp.setResult(IConstant.OP_SUCCESS);
                                smartResp.setMsg("密码修改成功");
                                smartResp.setData(null);
                            } else {
                                smartResp.setResult(IConstant.OP_FAIL);
                                smartResp.setMsg("密码修改失败");
                            }
                        } else {
                            smartResp.setMsg("旧密码输入错误");
                            smartResp.setData("2");
                        }
                    } else {
                        smartResp.setMsg("用户不存在");
                    }
                } else {
                    smartResp.setMsg("两次输入的密码不一致");
                    smartResp.setData("1");
                }
            }
        } catch (DaoException e) {
            throw new ServiceException(e.getMessage(), e.getCause());
        } catch (Exception e) {
            throw new ServiceException(e.getCause());
        }
        return smartResp;
    }

    /**
     * 获取学院用户树
     *
     * @param orgIds
     * @param userId 过滤用户
     * @return
     * @throws ServiceException
     */
    public SmartResponse<OrgUserZTreeData> getOrgUserZTree(List<String> orgIds, String userId) throws ServiceException {
        SmartResponse<OrgUserZTreeData> smartResp = new SmartResponse<OrgUserZTreeData>();
        List<TreeProp> ztreeProps = orgServ.getTree(orgIds);
        if (null != ztreeProps && ztreeProps.size() > 0) {
            String[] orgIdArray = new String[ztreeProps.size()];
            int count = 0;
            for (TreeProp treeProp : ztreeProps) {
                orgIdArray[count] = treeProp.getId();
                count++;
            }
            try {
                List<TNUser> users = userDao.queryByOrgIds(orgIdArray);
                if (null != users && users.size() > 0) {
                    TreeProp treeProp = null;
                    List<TreeProp> newTreeProp = new ArrayList<TreeProp>();
                    count = 1;
                    for (int i = 0; i < ztreeProps.size(); i++) {
                        newTreeProp.add(ztreeProps.get(i));
                        count++;
                        for (TNUser userTmp : users) {
                            if (ztreeProps.get(i).getId().equals(userTmp.getOrgId()) && !userId.equals(userTmp.getId())) {
                                treeProp = new TreeProp();
                                treeProp.setFlag("user");
                                treeProp.setId(userTmp.getId());
                                String fullName = userTmp.getFullName();
                                if (StringUtils.isEmpty(fullName))
                                    fullName = userTmp.getUsername();
                                treeProp.setName(fullName);
                                treeProp.setSortOrder(count);
                                treeProp.setParentId(ztreeProps.get(i).getId());
                                newTreeProp.add(treeProp);
                                count++;
                            }
                        }
                    }//for;
                    treeProp = null;
                    ztreeProps = null;
                    users = null;

                    ZTreeHelper<OrgUserZTreeData> zTreeHelper = new ZTreeHelper<OrgUserZTreeData>(OrgUserZTreeData.class, newTreeProp);
                    List<OrgUserZTreeData> ztreeDatas = zTreeHelper.convert("user");
                    zTreeHelper = null;
                    if (null != ztreeDatas && ztreeDatas.size() > 0) {
                        smartResp.setResult(IConstant.OP_SUCCESS);
                        smartResp.setMsg(IConstant.OP_SUCCESS_MSG);
                        smartResp.setDatas(ztreeDatas);
                    }
                    ztreeDatas = null;
                }
            } catch (DaoException e) {
                throw new ServiceException(e);
            } finally {
                orgIdArray = null;
            }
        }
        return smartResp;
    }

    /**
     * 获取学院用户树
     *
     * @param orgIds
     * @return
     * @throws ServiceException
     */
    public SmartResponse<OrgUserZTreeData> getOrgUserZTree(List<String> orgIds) throws ServiceException {
        SmartResponse<OrgUserZTreeData> smartResp = new SmartResponse<OrgUserZTreeData>();
        List<TreeProp> ztreeProps = orgServ.getTree(orgIds);
        if (null != ztreeProps && ztreeProps.size() > 0) {
            String[] orgIdArray = new String[ztreeProps.size()];
            int count = 0;
            for (TreeProp treeProp : ztreeProps) {
                orgIdArray[count] = treeProp.getId();
                count++;
            }
            try {
                smartResp = getOrgUserZTree(ztreeProps, userDao.queryByOrgIds(orgIdArray));
            } catch (DaoException e) {
                throw new ServiceException(e);
            } finally {
                orgIdArray = null;
            }
        }
        return smartResp;
    }

    /**
     * 获取学院用户树
     *
     * @param users
     * @return
     * @throws ServiceException
     */
    public SmartResponse<OrgUserZTreeData> getOrgUserZTreeByUser(List<TNUser> users) throws ServiceException {
        SmartResponse<OrgUserZTreeData> smartResp = new SmartResponse<OrgUserZTreeData>();
        if (null != users && users.size() > 0) {
            Set<String> orgIds = new HashSet<String>();
            for (TNUser user : users) {
                orgIds.add(user.getOrgId());
            }
            List<TreeProp> ztreeProps = orgServ.getTree(null);
            try {
                smartResp = getOrgUserZTree(ztreeProps, users);
            } catch (ServiceException e) {
                throw new ServiceException(e);
            } finally {
                orgIds = null;
            }
        }
        return smartResp;
    }

    /**
     * @param ztreeProps
     * @param users
     * @return
     * @throws ServiceException
     */
    private SmartResponse<OrgUserZTreeData> getOrgUserZTree(List<TreeProp> ztreeProps, List<TNUser> users) throws ServiceException {
        SmartResponse<OrgUserZTreeData> smartResp = new SmartResponse<OrgUserZTreeData>();
        if (null != users && users.size() > 0 && null != ztreeProps && ztreeProps.size() > 0) {
            int count = 0;
            TreeProp treeProp = null;
            List<TreeProp> newTreeProp = new ArrayList<TreeProp>();
            count = 1;
            for (int i = 0; i < ztreeProps.size(); i++) {
                newTreeProp.add(ztreeProps.get(i));
                count++;
                for (TNUser userTmp : users) {
                    if (ztreeProps.get(i).getId().equals(userTmp.getOrgId())) {
                        treeProp = new TreeProp();
                        treeProp.setFlag("user");
                        treeProp.setId(userTmp.getId());
                        String fullName = userTmp.getFullName();
                        if (StringUtils.isEmpty(fullName))
                            fullName = userTmp.getUsername();
                        treeProp.setName(fullName);
                        treeProp.setSortOrder(count);
                        treeProp.setParentId(ztreeProps.get(i).getId());
                        newTreeProp.add(treeProp);
                        count++;
                    }
                }
            }//for;
            treeProp = null;
            ztreeProps = null;
            users = null;
            ZTreeHelper<OrgUserZTreeData> zTreeHelper = new ZTreeHelper<OrgUserZTreeData>(OrgUserZTreeData.class, newTreeProp);
            List<OrgUserZTreeData> ztreeDatas = zTreeHelper.convert("user");
            zTreeHelper = null;
            treeCombinHelper.trimLeaf(ztreeDatas);
            if (null != ztreeDatas && ztreeDatas.size() > 0) {
                smartResp.setResult(IConstant.OP_SUCCESS);
                smartResp.setMsg(IConstant.OP_SUCCESS_MSG);
                smartResp.setDatas(ztreeDatas);
            }
            ztreeDatas = null;
        }
        return smartResp;
    }

    @Override
    public UserDao getDao() {
        return (UserDao) super.getDao();
    }

}
